import frappe
from frappe import _
from PIL import Image
import io
from frappe.utils import get_files_path, random_string
import re

def extract_last_number(last):
    """
    从LR1234B, LR-1234B, LR1234BX 提取 1234
    """

    match = re.search(r'\d{4,5}', last)
    return match.group() if match else None

@frappe.whitelist()
def optimize_image(docname, file_url):
    try:
        # Validate user has write permission on the Shoe Style document
        if not frappe.has_permission("Shoe Style", "write", docname):
            frappe.throw(_("You do not have permission to modify this Shoe Style document"))

        # Get the original file doc and its content in memory
        file_doc = frappe.get_doc("File", {"file_url": file_url})
        if not frappe.has_permission("File", "read", file_doc.name):
            frappe.throw(_("You do not have permission to read this file"))

        original_content = file_doc.get_content()  # Bytes of the file
        original_file_name = file_doc.file_name  # Keep the original filename
        original_size = len(original_content) / (1024 * 1024)  # Size in MB

        # Open and process the image in memory
        img = Image.open(io.BytesIO(original_content))
        
        # Convert RGBA to RGB if necessary (fix for JPEG format)
        if img.mode in ('RGBA', 'LA', 'P'):
            # Create a white background
            background = Image.new('RGB', img.size, (255, 255, 255))
            if img.mode == 'P':
                img = img.convert('RGBA')
            background.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
            img = background
        elif img.mode != 'RGB':
            img = img.convert('RGB')
        
        # Resize to max width of 600, maintain aspect ratio
        max_width = 600
        img.thumbnail((max_width, max_width * img.size[1] // img.size[0]), Image.Resampling.LANCZOS)
        
        # Convert to JPEG with 60% quality, save to memory
        output = io.BytesIO()
        img.save(output, format="JPEG", quality=60)
        output.seek(0)
        optimized_content = output.getvalue()
        new_size = len(optimized_content) / (1024 * 1024)  # Size in MB

        # Handle filename conflicts
        base_name, ext = original_file_name.rsplit(".", 1) if "." in original_file_name else (original_file_name, "")
        new_file_name = original_file_name
        counter = 1
        while frappe.db.exists("File", {
            "file_name": new_file_name,
            "attached_to_doctype": "Shoe Style",
            "attached_to_name": docname
        }):
            # If a file with the same name exists for this doc, append a random string or counter
            new_file_name = f"{base_name}-{random_string(6)}.{ext}" if ext else f"{base_name}-{random_string(6)}"
            counter += 1
            if counter > 10:  # Prevent infinite loops
                frappe.throw(_("Unable to generate a unique filename after multiple attempts"))

        # Delete the original file from ERPNext
        frappe.delete_doc("File", file_doc.name, delete_permanently=True)

        # Save the optimized image to ERPNext with the (potentially modified) filename
        new_file = frappe.utils.file_manager.save_file(
            fname=new_file_name,
            content=optimized_content,
            dt="Shoe Style",
            dn=docname,
            is_private=file_doc.is_private,
            decode=False
        )

        # Update the image_link field
        doc = frappe.get_doc("Shoe Style", docname)
        doc.image_link = new_file.file_url
        doc.save()

        # Clean up other files linked to this Shoe Style document
        existing_files = frappe.get_all(
            "File",
            filters={
                "attached_to_doctype": "Shoe Style",
                "attached_to_name": docname,
                "file_url": ["!=", new_file.file_url]
            },
            fields=["name"]
        )
        for f in existing_files:
            if frappe.has_permission("File", "delete", f.name):
                frappe.delete_doc("File", f.name, delete_permanently=True)

        frappe.db.commit()

        # Return success message
        return {
            "message": f"Picture optimized and attached successfully.<br>"
            f"Original size: {original_size:.2f} MB, New size: {new_size:.2f} MB"
        }
    except Exception as e:
        frappe.log_error(f"Image optimization failed: {str(e)}", "Optimize Image")
        frappe.throw(f"Failed to optimize image: {str(e)}")